package com.ltmonitor.jt808.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ltmonitor.jt808.protocol.IMessageBody;
import com.ltmonitor.jt808.protocol.T808Message;
import com.ltmonitor.jt808.protocol.T808MessageFactory;
import com.ltmonitor.jt808.protocol.T808MessageHeader;
import com.ltmonitor.jt808.tool.Tools;
import com.ltmonitor.util.DateUtil;

/**
 * 多分包的消息
 * 需要聚合多个分包，变成一个完整的包
 * @author admin
 *
 */
public class MultiPacketMessage {

	/**
	 * 数据包的key
	 */
	private String key;
	
	private int totalNum;
	
	private Date updateDate = new Date();
	/**
	 * 收到的所有分包
	 */
	private Map<Integer, byte[]> packets = new HashMap<Integer, byte[]>();
	
	
	private T808Message t808Message;
	/**
	 * 第一个分包的流水号
	 */
	private short messageSerialNo;
	
	private String simNo;
	
	/**
	 * 重传次数
	 */
	private int retransCount;
	
	private Date createDate = new Date();
	
	public MultiPacketMessage(T808Message msg)
	{
		T808MessageHeader header = msg.getHeader();
		this.totalNum = header.getMessageTotalPacketsCount();
		
		packets.put((int)header.getMessagePacketNo(), msg.getChildPacket());
		this.t808Message = msg;
		this.messageSerialNo = header.getMessageSerialNo();
		this.simNo = msg.getSimNo();
	}
	/**
	 * 判断所有的分包是否完整的收到
	 * @return
	 */
	public boolean isComplete()
	{
		return packets.size() == this.totalNum; 
	}
	
	
	public T808Message getWholeMessage()
	{
		if(isComplete() == false)
			return null;
		int totalLength = 0;
		
		List<byte[]> result = new ArrayList<byte[]>();
		for(int m = 1; m <= this.totalNum; m++)
		{
			byte[] data = packets.get(m);
			result.add(data);
			totalLength += data.length;
		}
		byte[] data = new byte[totalLength];
		int m = 0;
		for (byte[] b : result) 
		{
			System.arraycopy(b, 0, data, m,
				b.length);		
			m+= b.length;
		}
		IMessageBody body = T808MessageFactory.Create(
				this.t808Message.getMessageType(), data);
		this.t808Message.setMessageContents(body);
		return this.t808Message;
	}
	
	public List<byte[]> getWholePacket()
	{
		if(isComplete() == false)
			return null;
		List<byte[]> result = new ArrayList<byte[]>();
		for(int m = 1; m <= this.totalNum; m++)
		{
			byte[] data = packets.get(m);
			result.add(data);
		}
		return result;
	}
	/**
	 * 返回需要重新上传的数据分包号
	 * @return
	 */
	public ArrayList<Short> getNeedReTransPacketNo()
	{
		ArrayList<Short> result = new ArrayList<Short>();
		if(this.totalNum > this.packets.size())
		{
			for(int m = 1; m <= this.totalNum;m++)
			{
				if(packets.containsKey(m) == false)
					result.add((short)m);
			}
		}
		return result;
	}
	
	public boolean containPacket(int packetNo)
	{
		return packets.containsKey(packetNo);
	}
	
	public void addPacket(int packetNo, byte[] packetData)
	{
		packets.put(packetNo, packetData);
		this.updateDate = new Date();
	}
	
	
	public String toString()
	{
		double seconds = DateUtil.getSeconds(createDate, updateDate);

		String strMsgType = "0x" + Tools.ToHexString(t808Message.getMessageType(), 2);
		StringBuilder sb = new StringBuilder();
		sb.append(this.t808Message.getSimNo()).append(",消息类型:").append(strMsgType).append(",")
		.append(",总包数:").append(this.totalNum)
		.append(",已收到:").append(this.packets.size())
		.append(",重传次数:").append(this.retransCount)
		.append(",耗时:").append(seconds).append("秒");
		return sb.toString();
	}

	public int getTotalNum() {
		return totalNum;
	}

	public void setTotalNum(int totalNum) {
		this.totalNum = totalNum;
	}

	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

	public Map<Integer, byte[]> getPackets() {
		return packets;
	}

	public void setPackets(Map<Integer, byte[]> packets) {
		this.packets = packets;
	}
	
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public int getRetransCount() {
		return retransCount;
	}
	public void setRetransCount(int retransCount) {
		this.retransCount = retransCount;
	}
	public short getMessageSerialNo() {
		return messageSerialNo;
	}
	public void setMessageSerialNo(short messageSerialNo) {
		this.messageSerialNo = messageSerialNo;
	}
	public String getSimNo() {
		return simNo;
	}
	public void setSimNo(String simNo) {
		this.simNo = simNo;
	}
	
	
}
